local SEAL_UNBALANCE_DELAY  = 5 * TUNING.TOTAL_DAY_TIME  -- 5天后进入失衡
local SEAL_STRONG_DELAY     = 20 * TUNING.TOTAL_DAY_TIME -- 20天后进入强失衡
-- local SEAL_UNBALANCE_DELAY  = 10 -- 测试 10s
-- local SEAL_STRONG_DELAY     = 10 -- 测试 10s

local SealSinkholeManager   = Class(function(self, inst)
    self.inst = inst
    self.timer = inst.components.timer
    self.worldstate = inst.components.worldstate

    self.is_unbalanced = false
    self.is_strong_unbalanced = false

    -- 确保世界状态数据存在
    if self.worldstate then
        self.worldstate.data.isunbalanced = false
        self.worldstate.data.isstrongunbalanced = false
    end

    -- 注册监听计时器完成事件
    inst:ListenForEvent("timerdone", function(_, data)
        if data ~= nil then
            if data.name == "seal_unbalance" then
                self:SetUnbalanced(true)
            elseif data.name == "seal_strong_unbalance" then
                self:SetStrongUnbalanced(true)
            end
        end
    end)
end)

----------------------------------------------------------------
-- 常量配置
----------------------------------------------------------------
local STRONG_SPAWN_INTERVAL = 15 -- 每15秒检查一次
local STRONG_SPAWN_RADIUS   = 30 -- 检查已有敌人的范围
local STRONG_SPAWN_DIST     = 10 -- 生成半径
local STRONG_SPAWN_ATTEMPTS = 8  -- 寻路尝试次数

----------------------------------------------------------------
-- 工具函数：在指定玩家附近生成敌人
----------------------------------------------------------------

local function do_sleep_despawn(inst)
    inst:Remove()
end
local function OnEntitySleep(inst)
    inst._sleep_despawn_task = inst:DoTaskInTime(10, do_sleep_despawn)
end
local function OnEntityWake(inst)
    if inst._sleep_despawn_task then
        inst._sleep_despawn_task:Cancel()
        inst._sleep_despawn_task = nil
    end
end

local function TrySpawnEvolvedGestaltNearPlayer(player)
    -- 仅在强失衡状态下执行
    local mgr = TheWorld.components.sw_sealsinkholemanager
    if not mgr or not mgr.is_strong_unbalanced then
        return
    end

    local x, y, z = player.Transform:GetWorldPosition()

    if not TheWorld:HasTag("cave") then
        local existing = TheSim:FindEntities(x, y, z, STRONG_SPAWN_RADIUS, { "brightmare_guard" })
        for _, ent in ipairs(existing) do
            if ent.prefab == "gestalt_guard_evolved" then
                return -- 附近已有守卫，不再生成
            end
        end

        local offset = FindWalkableOffset(Vector3(x, y, z), math.random() * 2 * PI, STRONG_SPAWN_DIST, STRONG_SPAWN_ATTEMPTS, true)
        if offset ~= nil then
            local spawn_pt = Vector3(x + offset.x, 0, z + offset.z)
            local fx = SpawnPrefab("gestalt_guard_evolved")
            fx.Transform:SetPosition(spawn_pt:Get())
            fx:PushEvent("spawned")
        end
    else
        local NIGHTMARE_PREFABS = { "nightmarebeak", "crawlingnightmare", "ruinsnightmare" }
        local existing = TheSim:FindEntities(x, y, z, STRONG_SPAWN_RADIUS, { "nightmarecreature" })
        local count = 0
        for _, ent in ipairs(existing) do
            if table.contains(NIGHTMARE_PREFABS, ent.prefab) then
                count = count + 1
            end
        end

        if count >= 2 then
            return -- 附近已有足够的梦魇，不再生成
        end

        local offset = FindWalkableOffset(Vector3(x, y, z), math.random() * 2 * PI, STRONG_SPAWN_DIST, STRONG_SPAWN_ATTEMPTS, true)
        if offset ~= nil then
            local spawn_pt = Vector3(x + offset.x, 0, z + offset.z)
            local prefab = NIGHTMARE_PREFABS[math.random(#NIGHTMARE_PREFABS)]
            local fx = SpawnPrefab(prefab)
            fx.Transform:SetPosition(spawn_pt:Get())
            if fx.components.combat ~= nil then
                fx.components.combat:SuggestTarget(player)
            end
            fx.OnEntitySleep = OnEntitySleep
            fx.OnEntityWake = OnEntityWake
            fx.persists = false
        end
    end
end

function SealSinkholeManager:StartStrongUnbalanceSpawning()
    if self._spawn_task ~= nil then
        self._spawn_task:Cancel()
        self._spawn_task = nil
    end

    self._spawn_task = self.inst:DoPeriodicTask(STRONG_SPAWN_INTERVAL, function()
        if self.is_strong_unbalanced then
            for _, player in ipairs(AllPlayers) do
                if player ~= nil and player:IsValid() and not player:HasTag("playerghost") then
                    TrySpawnEvolvedGestaltNearPlayer(player)
                end
            end
        end
    end)
end

function SealSinkholeManager:StopStrongUnbalanceSpawning()
    if self._spawn_task ~= nil then
        self._spawn_task:Cancel()
        self._spawn_task = nil
    end
end

--------------------------------------------------------------
-- 进入 / 退出失衡状态
--------------------------------------------------------------
function SealSinkholeManager:SetUnbalanced(state)
    if self.is_unbalanced == state then
        return
    end

    self.is_unbalanced = state
    if self.worldstate then
        self.worldstate.data.isunbalanced = state
    end
    self.inst:PushEvent("seal_unbalanced_changed", { unbalanced = state })

    if state then
        TheNet:Announce(STRINGS.SW_STRINGS.SW_NET_INFO.UNBALANCED)

        -- 启动强失衡计时器
        if not self.timer:TimerExists("seal_strong_unbalance") then
            self.timer:StartTimer("seal_strong_unbalance", SEAL_STRONG_DELAY)
        end
    else
        -- 恢复平衡 → 取消所有计时器
        if self.timer:TimerExists("seal_unbalance") then
            self.timer:StopTimer("seal_unbalance")
        end
        if self.timer:TimerExists("seal_strong_unbalance") then
            self.timer:StopTimer("seal_strong_unbalance")
        end
        self:SetStrongUnbalanced(false)
    end
end

--------------------------------------------------------------
-- 进入 / 退出强失衡状态
--------------------------------------------------------------
function SealSinkholeManager:SetStrongUnbalanced(state)
    if self.is_strong_unbalanced == state then
        return
    end

    self.is_strong_unbalanced = state
    if self.worldstate then
        self.worldstate.data.isstrongunbalanced = state
    end
    self.inst:PushEvent("seal_strong_unbalanced_changed", { strong = state })

    if state then
        TheNet:Announce(STRINGS.SW_STRINGS.SW_NET_INFO.STRONG_UNBALANCED)
        self:StartStrongUnbalanceSpawning()
        Countprefabs_unbalanced()
    else
        self:StopStrongUnbalanceSpawning()
        Countprefabs_unbalanced()
    end
end

--------------------------------------------------------------
-- 外部调用：刷新状态（当镇守变化时调用）
--------------------------------------------------------------
function SealSinkholeManager:RefreshUnbalanceState()
    local total, sealed = Countprefabs()
    local all_sealed = total > 0 and sealed >= total
    local msg = string.format(STRINGS.SW_STRINGS.SW_NET_INFO.CAVES, total, sealed)
    TheNet:Announce(msg)
    print(msg)

    if all_sealed then
        if not self.timer:TimerExists("seal_unbalance") then
            TheNet:Announce(STRINGS.SW_STRINGS.SW_NET_INFO.ALL_SEALED)
            self.timer:StartTimer("seal_unbalance", SEAL_UNBALANCE_DELAY)
        end
    else
        if self.is_unbalanced or self.is_strong_unbalanced then
            TheNet:Announce(STRINGS.SW_STRINGS.SW_NET_INFO.PARTIALLY_SEALED)
        end
        self:SetUnbalanced(false)
    end
end

--------------------------------------------------------------
-- 存档 / 读档
--------------------------------------------------------------
function SealSinkholeManager:OnSave()
    return {
        is_unbalanced = self.is_unbalanced,
        is_strong_unbalanced = self.is_strong_unbalanced,
    }
end

function SealSinkholeManager:OnLoad(data)
    if data ~= nil then
        self.is_unbalanced = data.is_unbalanced or false
        self.is_strong_unbalanced = data.is_strong_unbalanced or false

        if self.is_strong_unbalanced then
            self:StartStrongUnbalanceSpawning()
        end

        if self.worldstate then
            self.worldstate.data.isunbalanced = self.is_unbalanced
            self.worldstate.data.isstrongunbalanced = self.is_strong_unbalanced
        end
    end
end

--------------------------------------------------------------
return SealSinkholeManager
